package ecBase;
import java.util.*;

/*
 * Individual.java
 * Created: 2005-11-30 10:20
 */
/**
 * An array-based implementation of Individual 
 *  for Counting-Ones problem.
 * @author T.S.Yo
 * @last updated 2005/12/14
**/

//public class Indgt extends Individual
//public class Individual extends IndProtype
//                        implements Cloneable,Comparator<Individual>
public class Individual implements Cloneable,Comparator<Individual>
{
    private String name = "Indgt";
    private int arraySize = 8;        // The default size of the geno-array
    private int[] gt;            // The chromosome: an array of gene 
    private double fitness = 0.0;      // The value of fitness 
    private boolean evaluated = false; // The flag indicate if this individual is evaluated

//---------------------------------------------------------------------
// Constructor    
    /** Random Constructor **/
    public Individual(){
        randGene();
        evalInd();
    }
    /** Random Constructor with given size**/
    public Individual(final int size){
        arraySize = size;
        randGene();
        evalInd();
    }
    /** Copy Constructor **/
    public Individual(final Individual ind){
        arraySize = ind.getArraySize();
        gt = new int[arraySize];
        setGenes(ind);
        evalInd();
    }
//---------------------------------------------------------------------
// Methods to access private members    
    // arraySize: 
    /** Returning the size of the bit array **/
    public int getArraySize(){
        return arraySize;
    }
    /** The arraySize cannot be changed after initialization **/
    public void setArraySize(int newSize){
        System.out.println("The arraySize cannot be changed after initialization");
    }
    
    // gt: 
    /** Randomly generate an array of Genotype **/
    public void randGene(){
        gt = new int[arraySize];
        Random rand = new Random();
        for (int i = 0; i < arraySize; i++){
            gt[i] = rand.nextInt(2);
        }
    }
    /** Retrieving gt **/
    public int[] getGenes(){
        return gt;
    }
    /** Replacing the the whole gt **/
    public void setGenes(final Individual ind){
        for (int i = 0; i < arraySize; i++){
            gt[i] = ind.getGenes()[i];
        }
    }
    /** Modifying the gt **/
    public void setGene(final int position, final int gene){
        int tmpGene = gene;
        gt[position].setGene(tmpGene);
    }

    // fitness and evaluated 
    /** evaluate the individual **/
    public void evalInd(){
        this.fitness = this.fitness();
        this.evaluated = true;
    }
//---------------------------------------------------------------------
// Overriding toString() to show the gt
    /** Overriding the toString()  method to show the content of the individual **/
    public String toString(){
        String output = new String(name);
        for (int i = 0; i < arraySize; i++){
           output = output + " " + gt[i].getGene();
        }
        return(output);
    }
    
    /** Overriding the comparator between Individuals  **/
    public int compareTo(final Individual ind){
        int comp = 0;
        if (this.fitness()!=ind.fitness()){
            return (int)(this.fitness()-ind.fitness());
        } else {
            for (int i = 0; i < arraySize; i++){
                if (gt[i].getGene() != ind.getGenes()[i].getGene()){
                    comp = gt[i].getGene() - ind.getGenes()[i].getGene();
                    break;
                }
            }
            return comp;
        }
    }
//
// Implementing the Comparator
    public int compare(Individual ind1, Individual ind2){
        return (ind1.compareTo(ind2));
    }
// Methods for Cloneable    
    /** Implementing clone() **/    public Object clone(){
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            throw new Error("This should not occur since we implement Cloneable");
        }
    }
//---------------------------------------------------------------------
// Evaluating the individual    /** The fitness of this individual : sum of fitness of each gene **/
    public double fitness(){
        double fit = 0.0;
        for (int i = 0; i < arraySize; i++){
           fit += gt[i].fitness();
        }
        return fit;       
    }
}